package java8;

import java.io.BufferedReader;
import java.io.StringReader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.IntSummaryStatistics;
import java.util.List;
import java.util.Optional;
import java.util.OptionalDouble;
import java.util.OptionalInt;
import java.util.stream.IntStream;
import java.util.stream.Stream;

public class StreamSample {

    public static void main(String[] args) throws Throwable {
        Stream<Integer> stream;
        // ===========================================================
        // 1. 生成流的方式
        // ===========================================================
        // 1.1 Stream.of
        // ==> 1, 3, 2, 3
        stream = Stream.of(1, 3, 2, 3);
        // 1.2 Stream.iterate, 第一个参数是起始值的种子, 相当于 i=1, i+=2
        // ==> 1, 3, 5, 7
        stream = Stream.iterate(1, i -> i += 2).limit(4);
        // 1.3 Stream.generate, 流中的每个元素都是通过供应者来生成
        // ==> 4个随机的double值
        Stream<Double> dStream = Stream.generate(Math::random).limit(4);
        // 1.4 Collection.stream(), 如集合 List、Set
        // ==> 1, 3, 2, 3
        List<Integer> list = new ArrayList<>();
        list.add(1);
        list.add(3);
        list.add(2);
        list.add(3);
        stream = list.stream();
        // 1.5 Arrays.stream
        // ==> 1, 3, 2, 3
        stream = Arrays.stream(new Integer[]{1, 3, 2, 3});
        // 1.6 BufferedReader.lines
        // ==> Hello
        // ==> World
        Stream<String> sStream = new BufferedReader(new StringReader("Hello\nWorld")).lines();
        // 1.7 IntStream/LongStream/DoubleStream.of(), iterate(), generate(); IntStream/LongStream.range()
        // ==> 0, 1, 2, 3, 4
        stream = IntStream.range(0, 5).boxed();
        // ===========================================================
        // 2. 筛选、过滤, 留下满足条件的元素
        // ===========================================================
        // 2.1 filter
        // ==> 3, 2, 3
        stream = Stream.of(1, 3, 2, 3).filter(i -> i > 1);
        // ===========================================================
        // 3. 获取或丢弃流前几个元素
        // ===========================================================
        // 3.1 limit 获取前几个元素
        // ==> 1, 3, 2
        stream = Stream.of(1, 3, 2, 3).limit(3);
        // 3.2 skip 丢弃前几个元素
        // ==> 2, 3
        stream = Stream.of(1, 3, 2, 3).skip(2);
        // ===========================================================
        // 4. 匹配
        // ===========================================================
        // 4.1 allMatch 所有元素都满足条件时返回真
        // ==> false
        boolean match1 = Stream.of(1, 3, 2, 3).allMatch(i -> i % 2 == 0);
        // 4.2 anyMatch 任意一元素满足条件时返回真
        // ==> true
        boolean match2 = Stream.of(1, 3, 2, 3).anyMatch(i -> i % 2 == 0);
        // 4.3 noneMatch 所有元素都不满足条件时返回真
        // ==> false
        boolean match3 = Stream.of(1, 3, 2, 3).noneMatch(i -> i % 2 == 0);
        // ===========================================================
        // 5. 查找
        // ===========================================================
        // 5.1 findFirst 查找第一个
        // ==> 2
        Optional<Integer> found1 = Stream.of(1, 3, 2, 4).filter(i -> i % 2 == 0).findFirst();
        // 5.2 findAny 随机查找一个, 实际查到第一满足条件即返回, 效果和findFirst一样
        // ==> 2
        Optional<Integer> found2 = Stream.of(1, 3, 2, 4).filter(i -> i % 2 == 0).findAny();
        // findAny 可以更好的利用并行流
        // ==> 2或4
        OptionalInt foundInt = IntStream.of(1, 3, 2, 4).parallel().filter(i -> i % 2 == 0).findAny();
        // ===========================================================
        // 6. 数值统计
        // ===========================================================
        // 6.1 count 元素个数
        // ==> 4
        long count = Stream.of(1, 3, 2, 4).count();
        // 6.2 max 最大值的元素
        // ==> 4
        Optional<Integer> max = Stream.of(1, 3, 2, 4).max(Integer::compareTo);
        // 6.3 min 最小值的元素
        // ==> 1
        Optional<Integer> min = Stream.of(1, 3, 2, 4).min(Integer::compareTo);
        // 6.4 sum 求和
        // ==> 10
        int sum = Stream.of(1, 3, 2, 4).mapToInt(i -> i).sum();
        // 6.5 average 求平均数
        // ==> 2.5
        OptionalDouble average = Stream.of(1, 3, 2, 4).mapToInt(i -> i).average();
        // 6.6 summaryStatistics 统计, 包括元素总个数、总和、最小值、最大值、平均数
        // ==> {count=4, sum=10, min=1, average=2.500000, max=4}
        IntSummaryStatistics statistics = Stream.of(1, 3, 2, 4).mapToInt(i -> i).summaryStatistics();
        // 6.7 reduce 元素归集, 将集合中的元素组合起来
        // ==> 10
        Optional<Integer> reduceOptional = Stream.of(1, 3, 2, 4).reduce(Integer::sum);
        // 可以设置初始种子的值
        // ==> 11
        Integer reduceInt = Stream.of(1, 3, 2, 4).reduce(1, Integer::sum);


        // ===========================================================
        // 7. 映射, 将流中的元素映射成另外一元素
        // ===========================================================
        // 7.1 map 映射流的元素
        // ==> A, C, B, D
        Stream<String> sMapStream = Stream.of(1, 3, 2, 4).map(i -> Character.toString((char) (i + 64)));
        // 7.2 mapToInt/mapToLong/mapToDouble 将流中的元素映射成 int/long/double
        //  ==> 1, 3, 2, 4
        IntStream intStream = Stream.of("1", "3", "2", "4").mapToInt(Integer::valueOf);
        // 7.3 flatMap 将流中每个数据都映射成另外一个流 (与 map 不同, map 是将流中的元素映射成另外一个元素)
        // ==> A, C, B, D
        Stream<String> strStream =
                // Stream<String> 类型
                Stream.of("This is the first line", "This is the second line")
                        // Stream<String[]> 类型
                        // ==> [This, is, the, first, line], [This, is, the, second, line]
                        .map(s -> s.split(" "))
                        // Stream<String>
                        // ==> This, is, the, first, line, This, is, the, second, line
                        .flatMap(Arrays::stream);
        // 7.2 flatMapToInt/flatMapToLong/flatMapToDouble 将流中的元素映射成对应的 IntStream/LongStream/DoubleStream
        //  ==> 1, 22, 333, 4, 55, 666, 7, 88, 999
        IntStream intStream1 = Stream.of(new int[]{1, 22, 333}, new int[]{4, 55, 666}, new int[]{7, 88, 999})
                .flatMapToInt(IntStream::of);

        // ===========================================================
        // 8. 排序
        // ===========================================================
        // 8.1 sort 默认自然排序
        // ==> 1, 2, 3, 4
        Stream<Integer> sortedInt = Stream.of(1, 3, 2, 4).sorted();
        // 倒序
        // ==> 4, 3, 2, 1
        sortedInt = Stream.of(1, 3, 2, 4).sorted(Comparator.reverseOrder());

        // ===========================================================
        // 9. 去重
        // ===========================================================
        // 9.1 distinct 去除重复元素
        // ==> 1, 3, 2
        Stream<Integer> distinctInt = Stream.of(1, 3, 2, 3).distinct();

        // ===========================================================
        // 10. 连接
        // ===========================================================
        // 10.1 concat 连接两个流
        // ==> 1, 3, 2, 4, 5, 7, 6, 8
        Stream<Integer> concatInt = Stream.concat(Stream.of(1, 3, 2, 4), Stream.of(5, 7, 6, 8));

        // ===========================================================
        // 11. 转数组
        // ===========================================================
        // 11.1 toArray 转 Object[] 数组
        // ==> [1, 3, 2, 4]
        Object[] objs = Stream.of(1, 3, 2, 4).toArray();

        // ===========================================================
        // 12. 遍历
        // ===========================================================
        // 12.1 forEach 转 Object[] 数组
        // ==> 1324
        Stream.of(1, 3, 2, 4).forEach(System.out::print);
        System.out.println();
        // forEachOrdered 按流中元素顺序迭代, 即使是并行操作, 顺序总是一致的. 而 forEach 在并行操作中结果顺序是不可靠的
        // ==> 1324
        IntStream.of(1, 3, 2, 4).parallel().forEachOrdered(System.out::print);

        // ===========================================================
        // 13. 收集 collect, 参考 CollectorsSample
        // ===========================================================

    }

}